package cn.jathlon.bigdata;

import gnu.trove.iterator.TLongDoubleIterator;
import gnu.trove.map.hash.TLongDoubleHashMap;

/**
 * 稀疏矩阵——空间和时间的折中
 * 矩阵元素值为double型
 * @author chen
 *
 */
public class SparseDoubleMatrix extends AbstractSparseMatrix{
	
    final int shift_row;  ///位移数
    final int mask;  ////掩码
    private TLongDoubleHashMap valueMap;  ////高效原生类型map
    
    public SparseDoubleMatrix(int numRows, int numColumn) {
        this.shift_row = minExponent(numColumn);
        this.mask = (1 << shift_row) - 1;
        valueMap = new TLongDoubleHashMap();
    }

    /**
     * set value.
     * @param row
     * @param col
     * @param value
     */
    public void setValue(int row, int col, double value){
    	valueMap.put(((long)row << shift_row) | col, value);
    }
    
    /**
     * Increments the primitive value mapped to key by 1.
     * @param row
     * @param col
     * @param value
     */
    public void increment(int row, int col){
    	valueMap.increment(((long)row << shift_row) | col);
    }
    
    /**
     * Adjusts the primitive value mapped to the key if the key is present in the map.
     * @param key
     * @param adjust_amount
     * @param put_amount
     */
    public void adjustOrPutValue(int row, int col, double adjust_amount, double put_amount) {
    	valueMap.adjustOrPutValue(((long)row << shift_row) | col, adjust_amount, put_amount);
    }

    /**
     *  Adjusts the primitive value mapped to key.
     * @param key
     * @param amount
     */
    public void adjustValue(int row, int col, int amount) {
    	valueMap.adjustValue(((long)row << shift_row) | col, amount);
    }
    
    /**
     * get value. 0 if not exist.
     * @param row
     * @param col
     * @return
     */
    public double getValue(int row, int col){
    	return valueMap.get(((long)row << shift_row) | col);
    }
    
    /**
     * iterator
     * @return
     */
	public TLongDoubleIterator iterator(){
		return valueMap.iterator();
	};


	////////////////
	public static void main(String[] args) {
		
		int row = 24234;
		int col = 463434;
		
		System.out.println(Integer.toBinaryString(row));
		System.out.println(Integer.toBinaryString(col));
		
		int shift = minExponent(col);
		int mask = (1 << shift) - 1;
		System.out.println(shift);
		System.out.println(Integer.toBinaryString(mask));
		
		long combine = ((long)row << shift) | col;
		System.out.println(Long.toBinaryString(combine));
		int col2 = (int)(combine & mask);  
		int row2 = (int)(combine >> shift) & mask;
		System.out.println(col2 + "  " + row2);
		
		//System.out.println(Integer.toBinaryString((1 << minExponent(shift_row)) - 1));
		
	}
	
	
	
}
